package naive2;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.json.JSONException;

import tools.DocRetriever;
import tools.LuceneNameRetriever;
import tools.QueryParser;
import tools.ResultOutput;
import edu.stanford.nlp.pipeline.StanfordCoreNLP;
import entities.Doc;
import entities.Entity;
import entities.Query;
import entities.Result;

//use naive bag of words methods
// there should b a normalization between all the entities in the same query that if they all have a word,
//that word should become not that important
public class NaiveLinking {
	private StanfordCoreNLP pipeline;
	private QueryParser qp;
	private LuceneNameRetriever lr;
	private LuceneJsonRetriever lj;
	private DocRetriever dr ;
	private Doc2BoW d2b;
	//private JsonEntity2BoW1 j2b;
	//private JsonEntity2BoW j2b;
	private Json2BoWStop j2b;
	public NaiveLinking(){
		
		Properties props = new Properties();
		props.put("annotators", "tokenize, ssplit, pos, lemma");
		this.pipeline = new StanfordCoreNLP(props);
		
		this.qp = new QueryParser("/largedata1/cmput696/students/lyao1/data/dev.xml");
		this.lr = new LuceneNameRetriever("/largedata1/cmput696/luceneIndex/lucene-a2e");
		//this.lj = new LuceneJsonRetriever("/largedata1/cmput696/luceneIndex/lucene-e2d");
		this.lj = new LuceneJsonRetriever("/largedata1/cmput696/students/lyao1/lemmaIndex");
		this.dr = new DocRetriever();
		this.d2b = new Doc2BoW(this.pipeline);
		//this.j2b = new JsonEntity2BoW1(this.pipeline);
		//this.j2b = new JsonEntity2BoW(this.pipeline);
		this.j2b = new Json2BoWStop(this.pipeline);
		
	}
	
	public void run() throws Exception{
		List<Query> qs = this.qp.getQueries();
		/*int limit = 1;
		
		
		String query = qs.get(1).getName();
		System.out.println("Query:"+query);
		System.out.println("Pos:"+qs.get(1).getBegin()+","+qs.get(1).getEnd());
		//ArrayList<Entity> es = this.lr.getEntities(query);
		Doc doc = this.dr.getDocById(qs.get(1).getDocid());
		System.out.println("Doc:"+doc.getText());
		BoW bow = this.d2b.doc2bow(doc); 
		//System.out.println("replaced Doc"+doc.getText().replaceAll("<.*?>", ""));
		System.out.println("Doc bow:");
		System.out.println(bow);
		
		
		Entity e = new Entity("Thomasville, Georgia");
		JsonEntity je = JsonEntity.instance(e, this.lj);
		BoW ebow = this.j2b.jentity2bow(je);
		System.out.println("Entity name:"+e.getName());
		System.out.println("Entity bow:");
		System.out.println(ebow);*/
		
		ArrayList<Result> rlist = new ArrayList<Result>();
		int count=0;
		int size = qs.size();
		for(Query query: qs){
			count++;
			Result r = this.processOnequery(query);
			rlist.add(r);
			System.out.println("curent:"+count+"/"+size);
		}
		
		ResultOutput rop = new ResultOutput("/largedata1/cmput696/students/lyao1/data/result.xml",this.qp.getQueryPath(),rlist);
		//rop.setNT(20);
		rop.setNT(40);
		rop.output_nt();
		
	}
	
	public Result processOnequery(Query query) throws Exception{
		
		//retireve doc based on query
		Doc doc = this.dr.getDocById(query.getDocid());
		
		System.out.println("start query:"+query.getName());
		long t1 = System.currentTimeMillis();
		BoW doc_bow = this.d2b.doc2bow(doc);
		
		//retrieve all the entities
		ArrayList<Entity> es =this.lr.getEntities(query.getName());
		
		for( Entity e: es){
			this.scoreAEntity(e, doc_bow);
		}
		
		Result result = new Result(query,es);
		
		long t2 = System.currentTimeMillis();
		
		System.out.println("finish queury:"+query.getName()+",time used:"+(t2-t1));
		return result;
	}
	
	public void scoreAEntity(Entity e,  BoW doc_bow) throws JSONException{
		//simple check how many words the have in common
		JsonEntity je = JsonEntity.instance(e, this.lj );
		BoW ebow = this.j2b.jentity2bow(je);
		
		
		e.setScore(doc_bow.inCommon(ebow));
		//e.setScore(doc_bow.inCommonTotal_normalized(ebow));
		
		//out put score and  words they had in common and their freq
		//System.out.println("Score situation for entity:"+e.getName() +"\t socre:"+e.getScore() +"\t total words in entity"+ebow.getTotalWords());
		//ebow.printCommon_normalized(doc_bow);
	}

	public static void main(String[] args){
		try{
			NaiveLinking nl = new NaiveLinking();
			nl.run();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
